<!-- 底部导航栏 -->
<template>
  <view class="u-tabbar">
    <view
      ref="u-tabbar__content"
      class="u-tabbar__content"
      :class="[border && 'u-border-top', fixed && 'u-tabbar--fixed', { 'mid-tabbar': midTabBar }]"
      :style="[tabbarStyle]"
      @touchmove.stop.prevent=""
    >
      <view class="u-tabbar__content__item-wrapper">
        <slot></slot>
      </view>
      <view v-if="safeAreaInsetBottom" :style="[{ height: safeBottomHeight + 'px' }]"></view>
    </view>
    <view
      v-if="placeholder"
      class="u-tabbar__placeholder"
      :style="{
        height: placeholderHeight + 'px',
      }"
    ></view>
  </view>
</template>

<script>
// #ifdef APP-NVUE
const dom = uni.requireNativePlugin('dom')
// #endif
/**
 * Tabbar 底部导航栏
 * @description 此组件提供了自定义tabbar的能力。
 * @property {String | Number}	value				当前匹配项的name
 * @property {Boolean}			safeAreaInsetBottom	是否为iPhoneX留出底部安全距离（默认 true ）
 * @property {Boolean}			border				是否显示上方边框（默认 true ）
 * @property {String | Number}	zIndex				元素层级z-index（默认 1 ）
 * @property {String}			activeColor			选中标签的颜色（默认 '#1989fa' ）
 * @property {String}			inactiveColor		未选中标签的颜色（默认 '#7d7e80' ）
 * @property {Boolean}			fixed				是否固定在底部（默认 true ）
 * @property {Boolean}			placeholder			fixed定位固定在底部时，是否生成一个等高元素防止塌陷（默认 true ）
 * @property {Object}			customStyle			定义需要用到的外部样式
 *
 */

import { deepMerge, addStyle, sleep } from '@/utils/helper'
import sheep from '@/sheep'

export default {
  name: 'SuTabbar',
  props: {
    customStyle: {
      type: [Object, String],
      default: () => ({}),
    },
    customClass: {
      type: String,
      default: '',
    },
    // 跳转的页面路径
    url: {
      type: String,
      default: '',
    },
    // 页面跳转的类型
    linkType: {
      type: String,
      default: 'navigateTo',
    },
    // 当前匹配项的name
    value: {
      type: [String, Number, null],
      default: '',
    },
    // 是否为iPhoneX留出底部安全距离
    safeAreaInsetBottom: {
      type: Boolean,
      default: true,
    },
    // 是否显示上方边框
    border: {
      type: Boolean,
      default: true,
    },
    // 元素层级z-index
    zIndex: {
      type: [String, Number],
      default: 10,
    },
    // 选中标签的颜色
    activeColor: {
      type: String,
      default: '#1989fa',
    },
    // 未选中标签的颜色
    inactiveColor: {
      type: String,
      default: '#7d7e80',
    },
    // 是否固定在底部
    fixed: {
      type: Boolean,
      default: true,
    },
    // fixed定位固定在底部时，是否生成一个等高元素防止塌陷
    placeholder: {
      type: Boolean,
      default: true,
    },
    midTabBar: {
      type: Boolean,
      default: false,
    },
  },
  data() {
    return {
      placeholderHeight: 0,
      safeBottomHeight: sheep.$platform.device.safeAreaInsets.bottom,
    }
  },
  computed: {
    tabbarStyle() {
      const style = {
        zIndex: this.zIndex,
      }
      // 合并来自父组件的customStyle样式
      return deepMerge(style, addStyle(this.customStyle))
    },
    // 监听多个参数的变化，通过在computed执行对应的操作
    updateChild() {
      return [this.value, this.activeColor, this.inactiveColor]
    },
    updatePlaceholder() {
      return [this.fixed, this.placeholder]
    },
  },
  watch: {
    updateChild() {
      // 如果updateChildren中的元素发生了变化，则执行子元素初始化操作
      this.updateChildren()
    },
    updatePlaceholder() {
      // 如果fixed，placeholder等参数发生变化，重新计算占位元素的高度
      this.setPlaceholderHeight()
    },
  },
  created() {
    this.children = []
  },
  mounted() {
    this.setPlaceholderHeight()
  },
  methods: {
    updateChildren() {
      // 如果存在子元素，则执行子元素的updateFromParent进行更新数据
      this.children.length && this.children.map((child) => child.updateFromParent())
    },
    getRect(selector, all) {
      return new Promise((resolve) => {
        uni
          .createSelectorQuery()
          .in(this)
          [all ? 'selectAll' : 'select'](selector)
          .boundingClientRect((rect) => {
            if (all && Array.isArray(rect) && rect.length) {
              resolve(rect)
            }
            if (!all && rect) {
              resolve(rect)
            }
          })
          .exec()
      })
    },
    // 设置用于防止塌陷元素的高度
    async setPlaceholderHeight() {
      if (!this.fixed || !this.placeholder) return
      // 延时一定时间
      await sleep(20)
      // #ifndef APP-NVUE
      this.getRect('.u-tabbar__content').then(({ height = 50 }) => {
        // 修复IOS safearea bottom 未填充高度
        this.placeholderHeight = height
      })
      // #endif

      // #ifdef APP-NVUE
      dom.getComponentRect(this.$refs['u-tabbar__content'], (res) => {
        const { size } = res
        this.placeholderHeight = size.height
      })
      // #endif
    },
  },
}
</script>

<style lang="scss" scoped>
.u-tabbar {
  display: flex;
  flex: 1;
  justify-content: center;

  &__content {
    display: flex;
    flex-direction: column;
    background-color: #fff;
    box-shadow: 0px -2px 4px 0px rgba(51, 51, 51, 0.06);

    &__item-wrapper {
      height: 50px;
      display: flex;
      justify-content: space-around;
      align-items: center;
    }
  }

  .mid-tabbar {
    border-radius: 30rpx 30rpx 0 0;
  }

  &--fixed {
    position: fixed;
    bottom: -1px;
    left: 0;
    right: 0;
  }
}
</style>
